package com.lwlk.util.rubbish;


import com.lwlk.util.functional.Action1;

import java.util.*;
import java.util.function.Predicate;

public class SwitchOrign {

    private SwitchOrign() { }

    public static <T> SwitchFlowEntity<T> should(FlowConds<T> conds) {

        return new SwitchFlowEntity<T>(conds);
    }

    public static <T> SwitchFlowEntity<T> should(FlowConds<T> conds, Action1<T> action) {

        return new SwitchFlowEntity<T>(conds, action);
    }

    public static <T> FlowCase<T> when(Predicate<T> predicate, Action1<T> action) {

        return new FlowCase<T>(predicate, action);
    }

    @SafeVarargs public static <T> FlowConds<T> usually(FlowCase<T> ... cases) {

        return new FlowConds<T>().addAll(cases);
    }

    public static <T> Action1<T> other(Action1<T> action) {

        return action;
    }

    public static <T> SwitchFlowEntity<T> flow(FlowConds<T> flowConds) {

        return new SwitchFlowEntity<>(flowConds);
    }

    public static <T> SwitchFlowEntity<T> flow(FlowConds<T> flowConds, Action1<T> other) {

        return new SwitchFlowEntity<T>(flowConds, other);
    }

    private static class SwitchFlowEntity<T> {

        private FlowConds<T> conds;

        private Action1<T> other = (e) -> {};

        public SwitchFlowEntity(FlowConds<T> flowConds) {

            this.conds = flowConds;
        }

        public SwitchFlowEntity(FlowConds<T> flowConds, Action1<T> other) {

            this.conds = flowConds;

            this.other = other;
        }

        public void dispatch(T ele) {

            conds.list.stream().filter((e) -> e.getPredicate().test(ele))
                    .findFirst()
                    .orElse(new FlowCase<>(null, other))
                    .getAction()
                    .call(ele);
        }
    }

    private static class FlowConds<T> {

        public List<FlowCase<T>> list = new ArrayList<>();

        @SafeVarargs public final FlowConds<T> addAll(FlowCase<T>... flowCases) {

            Collections.addAll(list, flowCases);

            return this;
        }
    }

    private static class FlowCase<T> {

        private Predicate<T> predicate;

        private Action1<T> action;

        public FlowCase(Predicate<T> predicate, Action1<T> action) {

            this.predicate = predicate;

            this.action = action;
        }

        public Predicate<T> getPredicate() {
            return predicate;
        }

        public Action1<T> getAction() {
            return action;
        }
    }

    public static void main(String[] args) {

        SwitchFlowEntity<Integer> sw = SwitchOrign.should(
                SwitchOrign.usually(
                        SwitchOrign.when((e) -> e.equals(0), (Integer e) -> System.out.println("is 0")),
                        SwitchOrign.when((e) -> e.equals(1), (Integer e) -> System.out.println("is 1"))
                ),
                SwitchOrign.other((e) -> System.out.println("WTF?")));

        sw.dispatch(0);

        sw.dispatch(1);

        sw.dispatch(100);
    }
}
